package tom_io_nio.nio.demo;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;

public class NioClient {

    private final InetSocketAddress serverAddress = new InetSocketAddress("127.0.0.1",8080);

    private Selector selector = null;

    private SocketChannel client = null;

    private String nickname = "";

    private static String USER_EXIST = "系统提示：该昵称已经存在，请换一个昵称";

    private static String USER_CONTENT_SPILIT = "#@#";

    private Charset charset = Charset.forName("UTF-8");

    public NioClient() throws IOException {
        //打开链接
        client = SocketChannel.open(serverAddress);
        //设置非阻塞
        client.configureBlocking(false);
        //获取selector
        selector = Selector.open();
        client.register(selector, SelectionKey.OP_READ);
    }

    public void session(){
        //开辟一个新线程从服务端读数据
        new Reader().start();
        //开辟一个新线程往服务端写数据
        new Writer().start();
    }

    private class Writer extends Thread{

        @Override
        public void run() {
            //在主线程中，从键盘读取数据输入到服务器端
            Scanner scanner = new Scanner(System.in);
            while (scanner.hasNextLine()){
                try{
                    String line = scanner.nextLine();
                    //不允许发空消息
                    if("".equals(line)){
                        continue;
                    }
                    if("".equals(nickname)){
                        nickname = line;
                        line = nickname + USER_CONTENT_SPILIT;
                    }else{
                        line = nickname + USER_CONTENT_SPILIT + line;
                    }
                    //client即能写也可以读，这边是读
                    client.write(charset.encode(line));
                }catch (IOException e){
                    e.printStackTrace();
                }
//                scanner.close();
            }
        }
    }

    private class Reader extends Thread{

        @Override
        public void run() {
            while(true){
                try{
                    int readyChannels = selector.select();
                    if(readyChannels==0){
                        continue;
                    }
                    Set<SelectionKey> KeySet = selector.selectedKeys();
                    Iterator<SelectionKey> selectionKeyIterator = KeySet.iterator();
                    while(selectionKeyIterator.hasNext()){
                        SelectionKey selectionKey = selectionKeyIterator.next();
                        selectionKeyIterator.remove();
                        process(selectionKey);
                    }
                }catch (IOException e){
                    e.printStackTrace();
                }

            }
        }
    }


    private void process(SelectionKey key)throws IOException{
        if(key.isReadable()){
            //使用NIO读取channel中的数据，这个和全局变量client是一样的，因为只注册了一个SocketChannel
            SocketChannel sc = (SocketChannel) key.channel();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            String content = "";
            while(sc.read(buffer) > 0){
                buffer.flip();
                content += charset.decode(buffer);
            }
            //若系统发送通知名字已存在，则需要换个昵称
            if(USER_EXIST.equals(content)){
                nickname= "";
            }
            System.out.println(content);
            key.interestOps(SelectionKey.OP_READ);
        }
    }

    public static void main(String[] args) throws IOException {
        new NioClient().session();
    }
}












